#include "color.h"
#include "ui_color.h"
#include "math.h"
#include "Mat.hpp"

Mat<float> img1(750, 500);

Mat<uchar> hsv2rgb(Mat<float> img);

color::color(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::color)
{
    ui->setupUi(this);
    this->setAttribute(Qt::WA_QuitOnClose, false);
    init_color();
}

color::~color()
{
    delete ui;
}

void color::init_color()
{
    connect(ui->slider_h, SIGNAL(valueChanged(int)), this, SLOT(img_preview()));
    connect(ui->slider_l, SIGNAL(valueChanged(int)), this, SLOT(img_preview()));
    connect(ui->slider_s, SIGNAL(valueChanged(int)), this, SLOT(img_preview()));
    connect(ui->check_preview, SIGNAL(clicked()), this, SLOT(img_preview()));
    connect(ui->slider_h, SIGNAL(valueChanged(int)), ui->spinBox_h, SLOT(setValue(int)));
    connect(ui->slider_l, SIGNAL(valueChanged(int)), ui->spinBox_l, SLOT(setValue(int)));
    connect(ui->slider_s, SIGNAL(valueChanged(int)), ui->spinBox_s, SLOT(setValue(int)));
    connect(ui->spinBox_h, SIGNAL(valueChanged(int)), ui->slider_h, SLOT(setValue(int)));
    connect(ui->spinBox_l, SIGNAL(valueChanged(int)), ui->slider_l, SLOT(setValue(int)));
    connect(ui->spinBox_s, SIGNAL(valueChanged(int)), ui->slider_s, SLOT(setValue(int)));
    connect(ui->btn_y, SIGNAL(clicked()), this, SLOT(btn_y_clicked()));
    connect(ui->btn_n, SIGNAL(clicked()), this, SLOT(btn_n_clicked()));
}
void color::receive_color_form_main(uchar ***a, int h1, int w)
{
    Mat<uchar> mat(a, h1, w);
    img1.Reshape(mat.Height(), mat.Width());
    float r, g, b;
    float h, s, v;
    for (int i = 0; i < mat.Height(); i++)
    {
        for (int j = 0; j < mat.Width(); j++)
        {
            b = mat.p->data[i][j][2];
            g = mat.p->data[i][j][1];
            r = mat.p->data[i][j][0];
            float max1 = max(r, max(g, b));
            float min1 = min(r, min(g, b));
            if (r == max1)
            {
                h = (g - b) / (max1 - min1);
            }
            if (g == max1)
            {
                h = 2 + (b - r) / (max1 - min1);
            }
            if (b == max1)
            {
                h = 4 + (r - g) / (max1 - min1);
            }
            h = h * 60.0;
            if (h < 0)
                h = h + 360;
            v = max1;
            s = (max1 - min1) / max1;
            img1.p->data[i][j][0] = h;
            img1.p->data[i][j][1] = s;
            img1.p->data[i][j][2] = v;
        }
    }
}
Mat<uchar> hsv2rgb(Mat<float> img)
{
    Mat<uchar> img1(img.Height(), img.Width());
    for (int i = 0; i < img.Height(); i++)
    {
        for (int j = 0; j < img.Width(); j++)
        {

            float R, G, B;
            if (img.p->data[i][j][1] == 0)
            {
                R = G = B = img.p->data[i][j][2];
            }
            else
            {
                img.p->data[i][j][0] = img.p->data[i][j][0] / 60.0;
                int k = (int)img.p->data[i][j][0];
                float f = img.p->data[i][j][0] - (float)k;
                float a = img.p->data[i][j][2] * (1 - img.p->data[i][j][1]);
                float b = img.p->data[i][j][2] * (1 - img.p->data[i][j][1] * f);
                float c = img.p->data[i][j][2] * (1 - img.p->data[i][j][1] * (1 - f));
                switch (k)
                {
                case 0:
                    R = img.p->data[i][j][2];
                    G = c;
                    B = a;
                    break;
                case 1:
                    R = b;
                    G = img.p->data[i][j][2];
                    B = a;
                    break;
                case 2:
                    R = a;
                    G = img.p->data[i][j][2];
                    B = c;
                    break;
                case 3:
                    R = a;
                    G = b;
                    B = img.p->data[i][j][2];
                    break;
                case 4:
                    R = c;
                    G = a;
                    B = img.p->data[i][j][2];
                    break;
                default:
                    R = img.p->data[i][j][2];
                    G = a;
                    B = b;
                    break;
                }
            }

            img1.p->data[i][j][2] = B;
            img1.p->data[i][j][1] = G;
            img1.p->data[i][j][0] = R;
        }
    }
    return img1;
}
void color::img_preview()
{
    if (ui->check_preview->isChecked())
    {
        int dh = ui->slider_h->value();
        int ds = ui->slider_s->value();
        int dl = ui->slider_l->value();

        Mat<float> img2(img1.Height(), img1.Width());
        img2.Copy(img2.p->data, img1.p->data, 1);
        for (int i = 0; i < img1.Height(); i++)
        {
            for (int j = 0; j < img1.Width(); j++)
            {
                img2.p->data[i][j][0] += dh;
                img2.p->data[i][j][0] = (int)img2.p->data[i][j][0] % 360;
                if (ds == -100)
                    img2.p->data[i][j][1] = 0;
                else
                    img2.p->data[i][j][1] += img2.p->data[i][j][1] * ds / 100.0;
                if (img2.p->data[i][j][1] > 255)
                    img2.p->data[i][j][1] = 255;
                img2.p->data[i][j][2] += img2.p->data[i][j][2] * dl / 100.0;
                if (img2.p->data[i][j][2] > 255)
                    img2.p->data[i][j][2] = 255;
            }
        }
        Mat<uchar> mat = hsv2rgb(img2);
        emit sendData(mat.p->data, 0);
    }
    else
        emit sendData(NULL, 2);
}
void color::btn_y_clicked()
{
    int dh = ui->slider_h->value();
    int ds = ui->slider_s->value();
    int dl = ui->slider_l->value();

    Mat<float> img2(img1.Height(), img1.Width());
    img2.Copy(img2.p->data, img1.p->data, 1);
    for (int i = 0; i < img1.Height(); i++)
    {
        for (int j = 0; j < img1.Width(); j++)
        {
            img2.p->data[i][j][0] += dh;
            img2.p->data[i][j][0] = (int)img2.p->data[i][j][0] % 360;
            if (ds == -100)
                img2.p->data[i][j][1] = 0;
            else
                img2.p->data[i][j][1] += img2.p->data[i][j][1] * ds / 100.0;
            img2.p->data[i][j][2] += img2.p->data[i][j][2] * dl / 100.0;
        }
    }
    Mat<uchar> mat = hsv2rgb(img2);
    emit sendData(mat.p->data, 1);

    this->close();
}
void color::btn_n_clicked()
{
    emit sendData(NULL, 2);
    this->close();
}